package com.wzh.barchart;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class BarChart extends View {

    private int width;   //控件宽度
    private int height;   //控件高度

    //自定义属性
    private int bottomTextSize;  //X轴底部文字大小
    private int axisTextSize;   //轴上的数字大小
    private int barWidth;   //柱宽度
    private int barInterval;  //柱间隔
    private boolean scrollable; //是否可左右滑动
    private int backgroudColor=0xff000000;   //图表背景颜色
    private int barClickedColor;   //柱形点击颜色
    private int barBackground;    //柱形颜色
    private boolean touchable;   //是否可点击
    private int yAxisNum;  //y轴点数量
    private int bottomHeight;  //x轴距底部距离
    private int lineColor;   //轴颜色
    private int lineTextColor;  //轴上的文字颜色
    private int yAxisMarginLeft;   //y轴距离左边距离
    private int yAxisMarginRight;   //y轴距离右边距离
    private int lineMarginTop;    //最顶上横线距离顶部距离
    private int axisNumOffsetX = 5;  //y轴数字距离轴距离
    private int axisNumOffsetY = 2;  //y轴数字距离轴数值偏移
    private int textRotateAnnge = 45;

    private int offset_x = 0;		// 移动的时候 x轴方向上 的偏移量  获取 点击区域的时候用
    private double scroll_rate = 0.7;//拖动灵敏度
    private int currentTouchIndexY=0;      //当前点击的柱的y高度
    private int currentTouchIndexX=0;      //当前点击的柱的x位置

    private List<String[]> values;
    private double valuesMax;
    private GestureDetector mGestureListener = null;

    private Paint mPaint;
    private TextPaint mTextPaint;

    public BarChart(Context context) {
        super(context);
        init(context,null);
    }

    public BarChart(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }

    public void setCanClickable(boolean clickable){
        this.touchable=clickable;
    }

    private void init(Context context, AttributeSet attrs){
        //初始化自定义属性
        if (attrs!=null){
            TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.BarChart);
            bottomTextSize = (int) typedArray.getDimension(R.styleable.BarChart_bottom_textsize,20);
            barWidth = (int)typedArray.getDimension(R.styleable.BarChart_bar_width,10);
            barInterval = (int)typedArray.getDimension(R.styleable.BarChart_bar_interval,10);
            scrollable = typedArray.getBoolean(R.styleable.BarChart_scrollable,false);
            backgroudColor = typedArray.getColor(R.styleable.BarChart_chart_backgroudcolor,0xffffffff);
            touchable = typedArray.getBoolean(R.styleable.BarChart_touchable,false);
            lineColor = typedArray.getColor(R.styleable.BarChart_lineColor,0xff000000);
            lineTextColor = typedArray.getColor(R.styleable.BarChart_lineTextColor,0xff000000);
            axisTextSize = (int)typedArray.getDimension(R.styleable.BarChart_axisTextSize,20);
            barBackground = typedArray.getColor(R.styleable.BarChart_barBackground,0xff000000);
            barClickedColor = typedArray.getColor(R.styleable.BarChart_barClickedColor,0xff000000);
        }
        bottomHeight = bottomTextSize *4;
        yAxisMarginLeft = bottomTextSize *3;
        yAxisMarginRight = 0;//bottomTextSize;
        lineMarginTop = bottomTextSize*2;
        mPaint = new Paint();
        mTextPaint = new TextPaint();
        mPaint.setAntiAlias(true);
        mTextPaint.setAntiAlias(true);
        mGestureListener = new GestureDetector(new MyGestureListener());
        this.setBackgroundColor(backgroudColor);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = measureSize(widthMeasureSpec);
        height = measureSize(heightMeasureSpec);
        setMeasuredDimension(width,height);
    }

    private int measureSize(int measureSpec){
        int result = 0;
        int size = MeasureSpec.getSize(measureSpec);
        int mode = MeasureSpec.getMode(measureSpec);
        //EXACTLY(精确模式)
        if (mode == MeasureSpec.EXACTLY){
            result = size;
        }else{
            result = 0;// 实际上需要自己计算
            //AT_MOST(至多模式)
            if (mode==MeasureSpec.AT_MOST){
                result = Math.min(result, size);
            }
        }
        return result;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画底部X轴
        mPaint.setColor(lineColor);
        mPaint.setStyle(Paint.Style.FILL);
        double xAxisMarginTop = height - bottomHeight;  //计算X轴的位置
        canvas.drawLine(yAxisMarginLeft,(float)xAxisMarginTop,width - yAxisMarginRight,(float)xAxisMarginTop,mPaint );
        mTextPaint.setColor(lineTextColor);
        mTextPaint.setTextAlign(Paint.Align.RIGHT);
        mTextPaint.setTextSize(axisTextSize);
        canvas.drawText("0",yAxisMarginLeft- axisNumOffsetX,(float)xAxisMarginTop,mTextPaint);

        //左边和右边y轴
        canvas.drawLine(yAxisMarginLeft,lineMarginTop,yAxisMarginLeft,height - bottomHeight,mPaint);
        int yWidthRight = width - yAxisMarginRight;
        //canvas.drawLine(yWidthRight,lineMarginTop,yWidthRight,height - bottomHeight,mPaint);

        //画柱状图中的横线
        int lineInterval = (height - lineMarginTop - bottomHeight)/yAxisNum;
        int lineNumDiff = (int) Math.ceil(valuesMax / yAxisNum);
        for (int i=0;i<yAxisNum;i++){
            //从底部向上画
            float xLinePosition = (float)xAxisMarginTop - lineInterval*(i+1);
            canvas.drawLine(yAxisMarginLeft,xLinePosition,yWidthRight,xLinePosition,mPaint);
            canvas.drawText(String.valueOf(lineNumDiff * (i+1)),yAxisMarginLeft-axisNumOffsetX,xLinePosition+axisNumOffsetY,mTextPaint);
        }

        //画柱形与底部文字
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(barBackground);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        for (int i=0;i<values.size();i++){
            float circleRadius = barWidth/2;
            float rectXLeft = yAxisMarginLeft+i*barWidth+(i+1)*barInterval;
            float rectXRight = rectXLeft + barWidth;
            float rectHeight = (float) (xAxisMarginTop - (xAxisMarginTop-lineMarginTop) * (Double.valueOf(values.get(i)[1])/valuesMax));
            RectF mRectf = new RectF(rectXLeft, rectHeight + circleRadius, rectXRight, (float)xAxisMarginTop);
            if (currentTouchIndexY>rectHeight && currentTouchIndexY<xAxisMarginTop
                    && currentTouchIndexX >rectXLeft && currentTouchIndexX<rectXRight) {
                mPaint.setColor(barClickedColor);
                canvas.drawText(values.get(i)[1],rectXLeft + (rectXRight - rectXLeft)/2,rectHeight - bottomTextSize/4,mTextPaint);
            }else {
                mPaint.setColor(barBackground);
            }
            canvas.drawRect(mRectf, mPaint);
            //canvas.drawCircle(rectXLeft + (rectXRight - rectXLeft) / 2, rectHeight + circleRadius, circleRadius, mPaint);

            float textYPotision = rectXLeft ;//文字绘制起点在柱形左端点//+ (rectXRight - rectXLeft)/2;
            canvas.save();
            canvas.rotate(-textRotateAnnge,textYPotision,(float)xAxisMarginTop + bottomTextSize);
            canvas.drawText(values.get(i)[0],textYPotision,(float)xAxisMarginTop + bottomTextSize*2,mTextPaint);
            canvas.restore();
            //处理柱形点击事件


        }
    }


    public List<String[]> initTestValue(){
        List<String[]> values = new ArrayList<>();
        for (int i=0;i<16;i++){
            String[] stringValues = new String[3];
            stringValues[0] = "省本级";
            Random random = new Random();
            stringValues[1] = String.valueOf(random.nextFloat()*1000);
            values.add(stringValues);
        }
        return values;
    }

    /**
     *
     * @param yAxisNum
     * @param values   String[0] X轴底部名字，String[1] 数值
     */
    public void initData(int yAxisNum, List<String[]> values){
        if (values == null || values.size()<=0){
            return;
        }
        this.yAxisNum = yAxisNum;
        this.values = values;
        valuesMax = Float.valueOf(values.get(0)[1]);
        for (int i=0;i<values.size();i++){
            if (Float.valueOf(values.get(i)[1]) > valuesMax){
                valuesMax = Float.valueOf(values.get(i)[1]);
            }
            Log.e("value",values.get(i)[1]);
        }
        valuesMax = (float) Math.ceil(valuesMax);
        Log.e("value","Max = "+valuesMax);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(null != mGestureListener){
            return mGestureListener.onTouchEvent(event);
        }
        return true;
    }

    /**
     * 触摸拖动
     *
     */
    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            if (scrollable){
                offset_x = offset_x + (int) (distanceX * scroll_rate);
                Log.e("onScroll","x:  "+offset_x);
                BarChart.this.scrollBy((int) (distanceX * scroll_rate), 0);
            }
            return true;
        }
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            return true;
        }
        @Override
        public void onShowPress(MotionEvent e) {
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            if (touchable) {
                int x = (int) e.getX();
                int y = (int) e.getY();
                currentTouchIndexY = y;
                int touchX = x + offset_x;//-xRelativeValue; //矫正触摸位置，设置模拟触摸位置相对于第一个柱子的右边位置
                if (touchX - barInterval < barWidth && touchX - barInterval > 0) {
                    Log.e("touch", 1 + "");
                } else if (touchX - barInterval > 0) {
                    Log.e("touch", touchX / (barWidth + barInterval) + 1 + "");
                }
                currentTouchIndexX = touchX;
                invalidate();
            }
            return true;
        }
    }
}
